 package ronin.scene;

 import java.awt.*;
 import java.awt.geom.*;
 import java.util.*;

 import ronin.actor2d.*;

 // the root node for QuadTree management
 public class QuadTree extends QuadNode 
 {

 	
 	// counter
 	private static int i, size;
 	
      // the overall depth of the tree
      protected int globalDepth;

      // a global linked list of leaf nodes
      public static LinkedList<QuadNode> leaves = new LinkedList<QuadNode>();

      // global linked list of objects that will be painted
      public static LinkedList<Moveable> paintList = new LinkedList<Moveable>();
      
      public Rectangle2D viewable;

      // creates a QuadTree with the sent depth, overall bounds, and viewable screen bounds
      public QuadTree(int depth, Rectangle2D r, Rectangle2D v)
      {
           super(null, depth, r, v);
           
           viewable = v;

           // global depth must be greater than zero
           if(depth <= 0)
           {
                throw new IllegalArgumentException("depth must be greater than zero");
           }

           globalDepth = depth;
          
           // initialize the overflow list
           objects = new LinkedList<Moveable>();
           

      }
      


      // adds a leaf node to the global leaf list
      public static void addLeaf(QuadNode node)
      {
           if(! leaves.contains(node))
           {
                leaves.add(node);
           }
      }

      // adds a Moveable object to the global paint list
      public static void addToPaintList(Moveable m)
      {
           if(! paintList.contains(m))
           {
           	//System.out.println("Paintlist add");
                paintList.add(m);
           }
      }

      // QuadTree must override insert method to deal with objects that are not within 
      // scene bounds
      public final void insert(Moveable c)
      {       
           // if the object is not within scene bounds, add it to the heap
           if(! viewable.contains(c.getBounds()) && ! viewable.intersects(c.getBounds()))
           {
                if(! objects.contains(c))
                {
                	//System.out.println("Overflowlist add");
                     objects.add(c);
                }
                
                
                return;
           }

  	   		// add the object to the global paint list
       		addToPaintList(c);

       		// try adding the object to all child nodes
       	
 //      	int i;
       	
           for(i = 0; i < 4; i++)
           {
                if(nodes[i] != null)
                {
                     nodes[i].insert(c, false);
                }
           }
      } 
      

      public final void update()
      {
  //    	int i;
      	
           // update the heap list
           //if(objects != null && !objects.isEmpty()) 
           //{
           	
     /*    int*/ size = objects.size();
      	
      	if(size != 0)
      	{ 
      	
	           for(i = 0; i < size; i++)
	           {
	                Moveable a = (Moveable) objects.get(i);
	                a.update();
	
	                // test if the object entered the tree; if so, insert it and remove it 
	                // from the heap
	                if(bounds.contains(a.getBounds()) || bounds.intersects(a.getBounds()))
	                {
	                     insert((Moveable) objects.remove(i), true);
	                     size--;
	                }
	            }
            }
           //}
           
          	size = leaves.size();

           //  update all leaf nodes for collisions and frame movement
           for(i = 0; i < size; i++) 
           {
                ((QuadNode) leaves.get(i)).update(viewable, paintList);	// ADDED viewable to test objects in node to add to paintList
           }
      }
      

      // paints all objects in the global paint list            
      public final void paint(Graphics2D g2d)
      {
           Actor2D a;
           
           int plSize = paintList.size();
           AffineTransform at = new AffineTransform();
 //          int i;
           for(i = 0; i < plSize; i++)
           {
                a = (Actor2D) paintList.get(i);
                
               g2d.setTransform(at);
               				   
               g2d.translate(0-viewable.getX(), 0-viewable.getY());
                a.paint(g2d);
			
			//	System.out.println("PL :" + a.getBounds().getHeight());
            
               /* // only paint the object if it is in bounds
                if(viewable.contains(a.getBounds()) || viewable.intersects(a.getBounds())) 
                {
                
                     a.paint(g2d);     
                } */
           }
      }
      

      // paints gridlines showing the bounds of each leaf node
      public final void paintBounds(Graphics2D g2d, Color color)
      {
      	QuadNode tnode;
      	
      	int lSize = leaves.size();
  //    	int i;
           // paint all leaf nodes
           for(i = 0; i < lSize; i++)
           {
           		tnode = (QuadNode)leaves.get(i);
           		
           	    if(viewable.contains(tnode.bounds) || viewable.intersects(tnode.bounds)) 
                {
                	tnode.paintBounds(g2d, color); 
                }
                
           }
      }

 }    // QuadTree